// 模块化
;(function (){
    // 构造函数
    function Promise(excutor){
        console.log( 'Promise构造函数...' );

        // this -> Promise的实例对象

        // 记录Promise对象的状态
        this.state = 'pending';

        // 记录Promise对象的结果
        this.result = undefined;

        // 缓存this指向
        var _this = this;
        // var that = this;
        // var self = this;

        // 缓存成功状态的回调函数
        this.resolves = [];

        // 缓存失败状态的回调函数
        this.rejects = [];

        // resolve函数，将Promise对象的状态从pending改变为fulfilled
        function resolve(resolveValue){
            console.log( 'resolve函数...' );

            // 判断当前Promise对象的状态
            if (_this.state !== 'pending') {
                // Promise对象的状态已改变，结束执行
                return;
            }

            // 记录状态
            _this.state = 'fulfilled';

            // 记录结果
            _this.result = resolveValue;

            // 判断resolves数组中是否有缓存的回调函数
            if (_this.resolves.length > 0) {
                setTimeout(function (){
                    // 遍历rejects数组，取出所有回调函数异步执行
                    _this.resolves.forEach(function (item){
                        item(_this.result);
                    })
                })
            }
        };

        // reject函数，将Promise对象的状态从pending改变为rejected
        function reject(rejectValue){
            console.log( 'reject函数...' );

            // 判断当前Promise对象的状态
            if (_this.state !== 'pending') {
                // Promise对象的状态已改变，结束执行
                return;
            }

            // 记录状态
            _this.state = 'rejected';

            // 记录结果
            _this.result = rejectValue;

            // 判断rejects数组中是否有缓存的回调函数
            if (_this.rejects.length > 0) {
                setTimeout(function (){
                    // 遍历rejects数组，取出所有回调函数异步执行
                    _this.rejects.forEach(function (item){
                            item(_this.result);
                    })
                })
            }
        }

        // excutor函数，同步执行
        try {
            // 捕获excutor函数内部的错误或抛出的值
            excutor(resolve,reject);
        } catch (error) {
            // 将Promise对象的状态从pending改变为rejected
            reject(error);
        }
    }

    // then方法（重点难点）
    Promise.prototype.then = function (resolveCallback,rejectCallback){
        console.log( 'then方法...' );

        // this -> Promise实例对象
        var _this = this;

        // 设置resolveCallback和rejectCallback的默认值
        resolveCallback = typeof resolveCallback === 'function' ? resolveCallback : function (res){return res;};
        rejectCallback = typeof rejectCallback === 'function' ? rejectCallback : function (res){throw res;};// throw将失败的结果传递下去

        // then方法执行后，返回一个新的Promise对象p2
        // return p2;
        // p2的状态和结果取决于p1的回调函数的返回值
        return new Promise(function (resolve,reject){
            // 封装公共逻辑
            function tryCatch(callback){
                try{
                    let result = callback(_this.result);
                    // result对象的整个原型链上是否出现Promise.prototype
                    if (result instanceof Promise) {
                        // result是Promise实例对象，p2的状态和结果跟随result的状态和结果
                        result.then(
                            function (res){// resolve
                                resolve(res);
                            },
                            function (res){// reject
                                reject(res);
                            }
                        )
                        // 上面的代码等价于如下：
                        // result.then(resolve,reject)
                    } else {
                        // result不是Promise实例对象，p2为成功状态
                        resolve(result);
                    }
                } catch(err){
                    // 出现异常情况，p2为失败状态
                    reject(err);
                }
            }

            // 判断Promise对象的状态
            if (_this.state === 'fulfilled') {
                // 成功状态，异步执行成功的回调函数
                setTimeout(function (){
                    // resolveCallback(_this.result);
                    tryCatch(resolveCallback);
                })
            }
            if (_this.state === 'rejected') {
                // 失败状态，异步执行失败的回调函数
                setTimeout(function (){
                    // rejectCallback(_this.result);
                    tryCatch(rejectCallback);
                })
            }
            if (_this.state === 'pending') {
                // 进行中状态，保存成功和失败的回调函数，将来状态改变之后调用
                // _this.resolves.push(resolveCallback);
                _this.resolves.push(function (){// item
                    tryCatch(resolveCallback);
                });

                // _this.rejects.push(rejectCallback);
                _this.rejects.push(function (){// item
                    tryCatch(rejectCallback);
                });
            }
        })
    }

    // catch方法
    Promise.prototype.catch = function (catchCallback){
        console.log( 'catch方法...' );

        // 利用then的失败回调函数来实现catch功能
        return this.then(null,catchCallback);
    }

    // all静态方法
    Promise.all = function (){
        console.log( 'all静态方法...' );
    }

    // race静态方法
    Promise.race = function (){
        console.log( 'race静态方法...' );
    }

    // 如何在自执行函数外部访问Promise函数？
    // return Promise; // 外部不能访问
    window.Promise = Promise;
})();
